﻿#pragma once

#ifndef BRIDGEANALYSIS_SAMPLING_H
#define BRIDGEANALYSIS_SAMPLING_H

// 采样数据管理器（线程安全封装）
class SpectrumDataManager
{
public:
    void addData(int32_t channel, const TRawItem &point);
    void clear();
    void clearChannel(int32_t chn);
    std::vector<TRawItem> getData(int32_t channel) const;

private:
    mutable std::mutex mutex_;
    std::unordered_map<int32_t, std::vector<TRawItem>> data_;
};

// 改进后的TChannelSampling类
class TChannelSampling
{
public:
    struct SamplingConfig
    {
        int32_t redis_timeout_msec;     // Redis超时N1毫秒未收到数据异常
        int32_t start_timeout_msec;     // 启动采样N2毫秒内数据未切变采样状态
        int32_t stop_timeout_msec;      // 停止采样N3毫秒内数据未切变基线状态
        int32_t stop_time_sync_msec;    // 停止时间与当前时间不同步，差异超N4毫秒
        int32_t gatcher_time_sync_msec; // 采样时长与方法时长不同步，差异超N5毫秒
        SamplingConfig()
        {
            redis_timeout_msec = 5000;
            start_timeout_msec = 5000;
            stop_timeout_msec = 5000;
            stop_time_sync_msec = 5000;
            gatcher_time_sync_msec = 5000;
        }
        SamplingConfig(const SamplingConfig &src)
        {
            assert(src.redis_timeout_msec >= 0 && src.redis_timeout_msec < 3600000);
            assert(src.start_timeout_msec >= 0 && src.start_timeout_msec < 3600000);
            assert(src.stop_timeout_msec >= 0 && src.stop_timeout_msec < 3600000);
            assert(src.stop_time_sync_msec >= 0 && src.stop_time_sync_msec < 3600000);
            assert(src.gatcher_time_sync_msec >= 0 && src.gatcher_time_sync_msec < 3600000);

            redis_timeout_msec = src.redis_timeout_msec;
            start_timeout_msec = src.start_timeout_msec;
            stop_timeout_msec = src.stop_timeout_msec;
            stop_time_sync_msec = src.stop_time_sync_msec;
            gatcher_time_sync_msec = src.gatcher_time_sync_msec;
        };
    };
    struct SamplingState
    {
        std::atomic<int64_t> step[C4] = {0, 0, 0, 0};
        std::atomic<int64_t> start_time[C4] = {0, 0, 0, 0};
        std::atomic<int64_t> stop_time[C4] = {0, 0, 0, 0};
        std::atomic<int64_t> gc_start_time[C4] = {0, 0, 0, 0};
        std::atomic<int64_t> gc_stop_time[C4] = {0, 0, 0, 0};
        std::atomic<int64_t> gc_last_value[C4] = {0, 0, 0, 0};
        std::atomic<bool> is_sampling{false};
        int32_t last_error_code;
        std::string last_error_message;
    };
    int64_t getOrgHandle();
    void setOrgHandle(int64_t handle);
    bool isSampling();
    bool isOrgHandleSampling(int64_t nHandle);
    bool ProcessSpectrumData_(int32_t InstID, int32_t detID, const std::vector<TRawItem> &data);
    bool ProcessSpectrumData(int32_t InstID, int32_t detID, const std::vector<TRawItem> &data);
    bool ProcessSpectrumData4Test(int32_t InstID, int32_t detID, const std::vector<TRawItem> &data);
    SamplingState *getSamplingState4Test()
    {
        return &state_;
    }
    void StartSampling();
    bool StopSampling();
    void saveDataToOrgFile();

    TChannelSampling(const SamplingConfig &config) : sampling_config_(config) {};
    ~TChannelSampling();

    bool hasError();
    void clearError();
    void setError(int32_t code, std::string message);
    int32_t getLastErrorCode() const;
    std::string getLastErrorMessage() const;

private:
    SamplingConfig sampling_config_;
    int64_t org_handle;
    SamplingState state_;
    SpectrumDataManager data_manager_;
    std::thread sampling_thread_;
    std::mutex org_mutex_;
    std::mutex process_mutex_;

    std::atomic<bool> data_updated_{false};
    mutable std::mutex error_mutex_;
};

extern std::unique_ptr<TChannelSampling> channel_sampling;
BRIDGE6DLL_API TChannelSampling *getChannelSamplingPtr();
#define CHECK_ORG_HANDLE_SAMPLING(nHandle)                                                                     \
    {                                                                                                          \
        if (channel_sampling && channel_sampling->isSampling() && channel_sampling->getOrgHandle() == nHandle) \
        {                                                                                                      \
            SET_ERROR_(ERR_CODE_ORG_HANDLE_IS_SAMPLING, ERR_MESSAGE_ORG_HANDLE_IS_SAMPLING, nHandle);          \
            return false;                                                                                      \
        }                                                                                                      \
    }
    
#endif
    